import { Injectable, Inject, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { PrismaService } from "src/prisma/prisma.service";
import { RedisService } from "src/redis/redis.service";
import { RegisterUserDto } from "./dto/register-user.dto";
import { LoginUser } from "./dto/login-user.dto";
import { UpdateUserPasswordDto } from "./dto/update-user-password.dto";
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UserService {

    @Inject(PrismaService)
    private prismaService: PrismaService;

    @Inject(RedisService)
    private redisService: RedisService;

    private logger = new Logger();

    async register(user: RegisterUserDto) {
        // 1.从redis读取验证码
        const captcha = await this.redisService.get(`captcha_${user.email}`);
        // 2.如果不存在失效
        if (!captcha) throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST);
        // 3.如果不正确，验证码不对
        if (user.captcha !== captcha) throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);
        // 4.查询用户是否存在（这也是为什么给用户名加唯一约束的原因）
        const foundUser = await this.prismaService.user.findUnique({
            where: {
                username: user.username
            }
        });
        // 5.用户存在，抛出异常
        if (foundUser) throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST);
        // 6.用户不存在，创建新用户
        try {
            return await this.prismaService.user.create({
                data: {
                    username: user.username,
                    password: user.password,
                    nickName: user.nickName,
                    email: user.email
                },
                select: {
                    id: true,
                    username: true,
                    email: true,
                    headPic: true,
                    createTime: true
                }
            });
        } catch (error) {
            // 错误的话，使用Logger记录一下错误日志
            this.logger.error(error, UserService);
            return null;
        }

    }

    async login(loginUser: LoginUser) {
        const foundUser = await this.prismaService.user.findUnique({
            where: {
                username: loginUser.username
            }
        });

        if (!foundUser) throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);

        // 这里我们没有对密码进行加密存储，后续可以加上
        if (foundUser.password !== loginUser.password) throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);

        delete foundUser.password;
        return foundUser;
    }

    async findUserDetailById(userId: number) {
        const user = await this.prismaService.user.findUnique({
            where: {
                id: userId
            },
            select: {
                id: true,
                username: true,
                nickName: true,
                email: true,
                headPic: true,
                createTime: true
            }
        });

        return user;
    }

    async updatePassword(passwordDto: UpdateUserPasswordDto) {
        // 1.判断验证码是否失效
        const captcha = await this.redisService.get(`update_password_captcha_${passwordDto.email}`);
        if (!captcha) throw new HttpException('验证码已经失效', HttpStatus.BAD_REQUEST);

        // 2.判断验证码是否正确
        if (passwordDto.captcha !== captcha) throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);

        // 3.更新用户密码信息
        const foundUser = await this.prismaService.user.findUnique({
            where: {
                username: passwordDto.username
            }
        });
        foundUser.password = passwordDto.password;
        try {
            await this.prismaService.user.update({
                where: {
                    id: foundUser.id
                },
                data: foundUser
            });

            return "密码修改成功"
        } catch (e) {
            this.logger.error(e, UserService);
            return "密码修改失败"
        }
    }

    async update(userId: number, updateUserDto: UpdateUserDto) {
        const captcha = await this.redisService.get(`update_user_captcha_${updateUserDto.email}`);

        if (!captcha) throw new HttpException('验证码已经失效', HttpStatus.BAD_REQUEST);

        if (captcha !== updateUserDto.captcha) throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);

        const foundUser = await this.prismaService.user.findUnique({
            where: {
                id: userId
            }
        });
        if (updateUserDto.nickName) {
            foundUser.nickName = updateUserDto.nickName
        };
        if (updateUserDto.headPic) {
            foundUser.headPic = updateUserDto.headPic;
        }

        try {
            await this.prismaService.user.update({
                where: {
                    id: userId
                },
                data: foundUser
            });
            return '用户信息修改成功';
        } catch (e) {
            this.logger.error(e, UserService);
            return '用户信息修改失败';
        }
    }

    async getFriendship(userId: number, name: string) {
        // 1.查询当前用户所有好友
        const friends = await this.prismaService.friendship.findMany({
            where: {
                OR: [
                    {
                        userId: userId
                    },
                    {
                        friendId: userId
                    }
                ]
            }
        });
        // 2.去除互为好友的重复数据
        const set = new Set<number>();
        for (let i = 0; i < friends.length; i++) {
            set.add(friends[i].userId);
            set.add(friends[i].friendId);
        }
        // 3.去除当前用户自身这条数据
        const friendIds = [...set].filter(item => item !== userId);
        // 4.根据去重后的用户ids，获取用户信息
        const res = [];
        for (let i = 0; i < friendIds.length; i++) {
            const user = await this.prismaService.user.findUnique({
                where: {
                    id: friendIds[i]
                },
                select: {
                    id: true,
                    username: true,
                    nickName: true,
                    email: true
                }
            });
            res.push(user);
        }

        return res.filter(item => item.nickName.includes(name));
    }
}
